package pri.zxx.webdemo.aop;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.support.AopUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import pri.zxx.webdemo.utils.GsonUtil;

import jakarta.servlet.http.HttpServletRequest;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * @author Twilight
 * @desc
 * @createTime 2020-07-10-21:33
 */
public class AopUtil {

	/**
	 * 获取注解
	 */
	public static Annotation getAnnotation(JoinPoint jp, Class<? extends Annotation> targetAnnotation) throws NoSuchMethodException {

		Method currentMethod = ((MethodSignature) (jp.getSignature())).getMethod();
		//获取当前方法注解
		Annotation annotation = currentMethod.getAnnotation(targetAnnotation);

		if (annotation == null) {
			//获取代理对象方法
			currentMethod = jp.getTarget().getClass().getMethod(currentMethod.getName(), currentMethod.getParameterTypes());
			annotation = currentMethod.getAnnotation(targetAnnotation);
		}

		Class<?> classTarget = AopUtils.getTargetClass(jp.getTarget());
		if (annotation == null) {
			//获取类上注解
			annotation = classTarget.getAnnotation(targetAnnotation);
		}
		if (annotation == null) {
			//获取接口上的注解
			Class<?>[] interfaces = classTarget.getInterfaces();
			Optional<Class<?>> first = Stream.of(interfaces).filter(aClass -> aClass.getAnnotation(targetAnnotation) != null).findFirst();
			if (first.isPresent()) {
				annotation = first.get().getAnnotation(targetAnnotation);
			}
		}
		if (annotation == null) {
			//获取接口方法的注解
			Class<?>[] interfaces = classTarget.getInterfaces();
			Method finalCurrentMethod = currentMethod;
			Optional<Method> first = Stream.of(interfaces)
					.flatMap(aClass -> {
						try {
							Stream<Method> method = Stream.of(aClass.getMethod(finalCurrentMethod.getName(), finalCurrentMethod.getParameterTypes()));
							return method;
						} catch (NoSuchMethodException e) {
							return null;
						}
					})
					.filter(Objects::nonNull)
					.findFirst();
			if (first.isPresent()) {
				annotation = first.get().getAnnotation(targetAnnotation);
			}
		}
		return annotation;
	}

	/**
	 * 打印请求参数
	 */
	public static String requestInfo(HttpServletRequest request, JoinPoint jp) {
		StringBuilder requestLog = new StringBuilder();
		requestLog.append("\n -> 请求URL = {").append(request.getRequestURI()).append("},")
				.append("\n -> 请求方式 = {").append(request.getMethod()).append("},")
				.append("\n -> 请求IP = {").append(request.getRemoteAddr()).append("},")
				.append("\n -> 请求方法 = {").append(jp.getSignature().getDeclaringTypeName()).append(".").append(jp.getSignature().getName()).append("},");

		for (Object arg : jp.getArgs()) {
			if (arg instanceof ServletRequest || arg instanceof ServletResponse || arg instanceof MultipartFile || arg instanceof BindingResult) {
				break;
			}
			requestLog.append("\n -> 请求参数 = ").append(GsonUtil.gson.toJson(arg == null ? "" : arg)).append(",");
		}
		return requestLog.toString();
	}
}
